/**
 * 
 */
package com.lorizz.picpub.web.controller.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;

import com.lorizz.picpub.query.UpmQueries;
import com.lorizz.picpub.web.Constants;
import com.lorizz.picpub.web.controller.ImageController;
import com.lorizz.upm.Album;
import com.lorizz.upm.Image;
import com.lorizz.upm.ImageVariant;
import com.lorizz.upm.np.AlbumNP;
import com.lorizz.upm.np.ImageNP;
import com.lorizz.upm.np.ImageVariantNP;
import com.lorizz.upm.np.NPUtils;
import com.lorizz.upm.np.UserProfileNP;
import com.lorizz.upm.repository.Repository;

/**
 * @author wind hong
 * 
 */
public class ImageControllerImpl implements ImageController {

    private Repository upmRepository;

    public void setUpmRepository(Repository upmRepository) {
        this.upmRepository = upmRepository;
    }

    @Override
    public String albums(HttpSession session, Model model) {
        UserProfileNP userProfile = (UserProfileNP) session.getAttribute(Constants.SESSION_USERPROFILE);
        return albums(userProfile.getId(), model);
    }

    @Override
    public String albums(long userProfileId, Model model) {
        List<Album> albums = upmRepository.executeQuery(UpmQueries.instance().albums(userProfileId));
        List<Object[]> albumIdsCounts1stImg = upmRepository.executeQuery(UpmQueries.instance()
                .albumIdsWithImageCountsAnd1stImageId(userProfileId));
        //
        Map<Long, Long> imageCounts = new HashMap<Long, Long>();
        for (Album album : albums) {
            boolean found = false;
            for (Object[] o : albumIdsCounts1stImg) {
                if (album.getId().equals(o[0])) {
                    found = true;
                    imageCounts.put(album.getId(), (Long) o[1]);
                    break;
                }
            }
            if (!found) {
                imageCounts.put(album.getId(), 0L);
            }
        }
        //
        List<Long> imgIds = new ArrayList<Long>();
        for (Object[] o : albumIdsCounts1stImg) {
            imgIds.add((Long) o[2]);
        }
        Map<Long, ImageVariantNP> imageVars = new HashMap<Long, ImageVariantNP>();
        if (!imgIds.isEmpty()) {
            List<Object[]> imgVars = upmRepository.executeQuery(UpmQueries.instance().imageVariantsWithImageIds(imgIds,
                    "thumbnail.middle"));
            for (Object[] o : imgVars) {
                Long imgId = (Long) o[0];
                for (Object[] o1 : albumIdsCounts1stImg) {
                    if (imgId.equals(o1[2])) {
                        imageVars.put((Long) o1[0], NPUtils.packageImageVariant((ImageVariant) o[1]));
                        break;
                    }
                }
            }
        }
        //
        List<AlbumNP> albumNPs = NPUtils.packageAlbumList(albums);
        for (AlbumNP albumNP : albumNPs) {
            albumNP.setUserProfile(NPUtils.packageUserProfile(albums.get(0).getUserProfile()));
        }
        //
        model.addAttribute("albums", albumNPs);
        model.addAttribute("imageCounts", imageCounts);
        model.addAttribute("imageVars", imageVars);
        return "albums";
    }

    @Override
    public String album(Model model) {
        model.addAttribute("album", new AlbumNP());
        return "album";
    }

    @Override
    public String album(AlbumNP albumNP, BindingResult result, HttpSession session, Model model) {
        UserProfileNP userProfileNP = (UserProfileNP) session.getAttribute(Constants.SESSION_USERPROFILE);
        if (userProfileNP == null)
            return "redirect:/signin";
        validate(albumNP, result, userProfileNP.getId());
        if (result.hasErrors()) {
            return "album";
        }
        Album album = upmRepository.createAlbum();
        album.setTitle(albumNP.getTitle());
        album.setUserProfile(upmRepository.loadUserProfile(userProfileNP.getId()));
        upmRepository.persist(album);
        return "redirect:/i/albums";
    }

    private void validate(AlbumNP album, Errors errors, long userProfileId) {
        ValidatorUtils.NotEmpty("title", album.getTitle(), errors, "album.error.title.empty");
        if (!errors.hasErrors()) {
            List<Album> albums = upmRepository.executeQuery(UpmQueries.instance()
                    .album(album.getTitle(), userProfileId));
            if (!albums.isEmpty()) {
                errors.rejectValue("title", "album.error.title.exist");
            }
        }
    }

    @Override
    public String images(long albumId, int pageSize, int page, Model model) {
        List<Long> totals = upmRepository.executeQuery(UpmQueries.instance().imageCount(albumId));
        int total = totals.get(0).intValue();
        if (pageSize < 1) 
            pageSize = 30;
        int totalPages = (total / pageSize) + ((total % pageSize) > 0 ? 1 : 0);
        if (page < 0)
            page = 1;
        if (page > totalPages)
            page = totalPages;
        int first = pageSize * (page - 1);
        
        List<ImageNP> imageNPs = new ArrayList<ImageNP>();
        if (total == 0) {
            model.addAttribute("images", imageNPs);
            return "images";
        }
        
        List<Image> images = upmRepository.executeQuery(UpmQueries.instance().images(albumId), first, pageSize);
        for (Image image : images) {
            List<ImageVariantNP> vars = NPUtils.packageImageVariantList(image.getImageVariants());
            ImageNP imageNP = NPUtils.packageImage(image);
            imageNP.getImageVariants().addAll(vars);
            imageNPs.add(imageNP);
        }
        model.addAttribute("images", imageNPs);
        return "images";
    }

    @Override
    public String images(long albumId, long imageId, Model model) {
        List<Long> lessThanTotals = upmRepository.executeQuery(UpmQueries.instance().imageCountLessThan(albumId, imageId));
        int lessThanTotal = lessThanTotals.get(0).intValue();
        int pageSize = 30;
        int page = lessThanTotal / pageSize + 1;
        return String.format("redirect:/i/v/%d-%d-%d", albumId, pageSize, page);
    }

	@Override
	public String image(long imageId, Model model) {
		Image image = upmRepository.loadImage(imageId);
		ImageNP imageNP = NPUtils.packageImage(image);
		imageNP.getImageVariants().addAll(NPUtils.packageImageVariantList(image.getImageVariants()));
		model.addAttribute("image", imageNP);
		return "image";
	}
}
